
#include "core.h"
#include "connection.h"
#include "event.h"

listening_t *init_listening(cycle_t *cycle)
{
	listening_t *ls;
	size_t	len;
	struct sockaddr_in *sin;
	array_t	array;

	array_init(&array, cycle->pool, 10, sizeof(listening_t));
	array_create(cycle->pool, 10, sizeof(listening_t));

	//只存放一个监听,以后根据配置文件填充
	ls = array_push(&cycle->listening);

	sin = pcalloc(cycle->pool, sizeof(struct sockaddr_in));

	sin->sin_family	= AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	sin->sin_port	= htons(8888);

	ls->fd	= -1;
	ls->family = AF_INET;
	ls->backlog = 511;
	ls->rcvbuf = 4096;
	ls->sndbuf = 60000;
	ls->post_accept_timeout = 1000;
	
	ls->type = SOCK_STREAM;
	ls->sockaddr = (struct sockaddr*)sin;
	ls->socklen = sizeof(struct sockaddr_in);
	ls->handler = init_connection;

	if (verbose)
		printf("%s, %d, %s\n", __FILE__, __LINE__, __func__);
		
	return ls;
}

int open_listening_sockets(cycle_t *cycle)
{
	int	reuseaddr;
	int	i, tries, failed;
	log_t	*log;
	int	s;
	listening_t	*ls;

	reuseaddr	= 1;

	log = cycle->log;


	for (tries=5; tries; tries--){

		failed = 0;

		ls = cycle->listening.elts;
		printf("\nlistening NO. = %d\n", cycle->listening.nelts);

		for (i=0; i<cycle->listening.nelts; i++){
			if (ls[i].ignore)
				continue;

			if (ls[i].fd != -1)
				continue;

			s	= socket(ls[i].family, ls[i].type, 0);
			
			if (verbose)
				printf("listen fd = %d\n", s);

			if (s == -1){
				fprintf(stderr, "socket() failed.\n");
				close(s);
				return -1;
			}

			if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *)&reuseaddr, sizeof(int)) == -1){
				close(s);
				fprintf(stderr, "setsockopt() failed.\n");
				return -1;
			}
			if (set_nonblocking(s) == -1){
				close(s);
				fprintf(stderr, "nonblocking() failed.\n");
				return -1;
			}
			if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1){
				close(s);
				fprintf(stderr, "nonblocking() failed.\n");
				if (errno == EADDRINUSE)
					return E_FAIL;

				failed = 1;
				continue;
			}
			if (listen(s, ls[i].backlog) == -1){
				close(s);
				fprintf(stderr, "nonblocking() failed.\n");
				return -1;
			}

			ls[i].listen = 1;
			ls[i].fd = s;
		}

		if (!failed)
			break;

		sleep(3);
	}

//	if (verbose)
//		printf("%s, %d, %s\n", __FILE__, __LINE__, __func__);

	return E_OK;	
}

void configure_listening_sockets(cycle_t *cycle)
{
	int	keepalive;
	int	i, timeout;
	listening_t	*ls;

	ls = cycle->listening.elts;
	for (i=0; i<cycle->listening.nelts; i++){
		if (ls[i].rcvbuf){
			if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (const void *)&ls[i].rcvbuf, sizeof(int)) == -1){
				fprintf(stderr, "setsockopt(rcvbuf).\n");
			}
		}
		
		if (ls[i].sndbuf){
			if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (const void *)&ls[i].sndbuf, sizeof(int)) == -1){
				fprintf(stderr, "setsockopt(sndbuf).\n");
			}
		}
/*
		if (ls[i].keepidle){
			if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE, (const void *)&ls[i].keepidle, sizeof(int)) == -1){
				fprintf(stderr, "setsockopt(keepalive).\n");
			}
		}
	
		if (ls[i].keepintvl){
			if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL, (const void *)&ls[i].keepintvl, sizeof(int)) == -1){
				fprintf(stderr, "setsockopt(keepintvl).\n");
			}
		}

		if (ls[i].keepcnt){
			if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT, (const void *)&ls[i].keepcnt, sizeof(int)) == -1){
				fprintf(stderr, "setsockopt(keepcnt).\n");
			}
		}
	
		int timeout = 10;
		if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(int)) == -1){
				fprintf(stderr, "setsockopt(keepcnt).\n");
		}
			
*/
		if (ls[i].listen){
			if (listen(ls[i].fd, ls[i].backlog) == -1){
				close(ls[i].fd);
				fprintf(stderr, "nonblocking() failed.\n");
				return ;
			}
		}
	}

//	if (verbose)
//		printf("%s, %d, %s\n", __FILE__, __LINE__, __func__);

	return ;
}

connection_t *get_connection(int s)
{
	int	instance;
	event_t	*rev, *wev;
	connection_t *c;

	c = g_cycle->free_connections;	//取数组,链表的首地址
	if (c == NULL){
		fprintf(stderr, "%s, %d, %s, %d failed.\n", __FILE__, __LINE__, __func__, errno);
		return NULL;
	}

	g_cycle->free_connections = c->data;
	g_cycle->free_connection_n--;

	rev = c->read;
	wev = c->write;

	memset(c, 0, sizeof(connection_t));

	c->read= rev;
	c->write = wev;
	c->fd = s;

	instance = rev->instance;

	memset(rev, 0, sizeof(event_t));
	memset(wev, 0, sizeof(event_t));

	rev->instance	= !instance;
	wev->instance	= !instance;

	rev->index = -1;
	wev->index = -1;

	rev->data = c;
	wev->data = c;
	
	return c;
}


void free_connection(connection_t *c)
{
	c->data = g_cycle->free_connections;
	g_cycle->free_connections = c;
	g_cycle->free_connection_n++;

	if (verbose)
		printf("%s == %d, %s\n", __FILE__, __LINE__, __func__);

	if (g_cycle->files)
		g_cycle->files[c->fd] = NULL;
}
void close_connection(connection_t *c)
{
	int	fd;
	if (c->fd == -1)
		return;

	accept_mutex_held = 0;;
	use_accept_mutex = 0;
	
	if (c->read->timer_set)
		event_del_timer(c->read);
	if (c->write->timer_set)
		event_del_timer(c->write);

	epoll_del_connection(c, CLOSE_EVENT);				
	
	c->read->closed = 1;
	c->write->closed = 1;

	free_connection(c);	

	fd = c->fd;
	c->fd = -1;

	close(fd);
}

void close_listening_sockets(cycle_t *cycle)
{
	int	i;
	listening_t	*ls;
	connection_t	*c;

	accept_mutex_held = 0;
	use_accept_mutex = 0;

	ls = cycle->listening.elts;
	for (i=0; i<cycle->listening.nelts; i++){
		c = ls[i].connection;
		if (c->read->active){
			epoll_del_event(c->read, READ_EVENT, 0);
		}
		free_connection(c);
		c->fd = -1;
		close(ls[i].fd);
	}
}

